/**
* SMain - This activity handles the main window, it displays the curently 
*         selected URI and availiable bookmarks, It contains BookmarkDialog to 
*         create/edit bookmarks.
*/

package koutei.stream;

import android.app.Activity;
import android.app.Dialog;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Button;
import android.widget.Toast;
import android.widget.RadioGroup;
import android.widget.RadioButton;
import android.widget.ArrayAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnKeyListener;
import android.view.View.OnClickListener;
import android.view.KeyEvent;
import android.net.Uri;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.text.Selection;
import android.text.TextWatcher;
import android.text.Editable;
import java.io.File;

public class SMain extends Activity{
    public final static String NO_URL = "http://";
    public final static String FILE_URL = "/sdcard/";
    public final static String PLAY_ACTION="koutei.stream.Stream.PLAY";
    public final static String TAG = "SMAIN";
    public final static String FILE_SCHEMA = "file:";
    public final static int CREATE_ID = 0;
    public final static int EDIT_ID = 1;
    public final static int DELETE_ID = 2;
    public final static int NONE = -1;
    public final static int[] NON_MODIFIER_KEYS = {
        KeyEvent.KEYCODE_DPAD_CENTER, 
        KeyEvent.KEYCODE_DPAD_DOWN, 
        KeyEvent.KEYCODE_DPAD_LEFT,
        KeyEvent.KEYCODE_DPAD_RIGHT, 
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_ALT_LEFT, 
        KeyEvent.KEYCODE_ALT_RIGHT,
        KeyEvent.KEYCODE_CALL, 
        KeyEvent.KEYCODE_CAMERA,
        KeyEvent.KEYCODE_ENDCALL, 
        KeyEvent.KEYCODE_ENVELOPE,
        KeyEvent.KEYCODE_EXPLORER, 
        KeyEvent.KEYCODE_FOCUS,
        KeyEvent.KEYCODE_HEADSETHOOK, 
        KeyEvent.KEYCODE_HOME,
        KeyEvent.KEYCODE_BACK,
        KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, 
        KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
        KeyEvent.KEYCODE_MEDIA_PREVIOUS, 
        KeyEvent.KEYCODE_MEDIA_REWIND,
        KeyEvent.KEYCODE_MEDIA_STOP, 
        KeyEvent.KEYCODE_MENU,
        KeyEvent.KEYCODE_MUTE, 
        KeyEvent.KEYCODE_NOTIFICATION,
        KeyEvent.KEYCODE_POWER, 
        KeyEvent.KEYCODE_SEARCH,
        KeyEvent.KEYCODE_SHIFT_LEFT, 
        KeyEvent.KEYCODE_SHIFT_RIGHT,
        KeyEvent.KEYCODE_SOFT_LEFT, 
        KeyEvent.KEYCODE_SOFT_RIGHT,
        KeyEvent.KEYCODE_SYM,
        KeyEvent.KEYCODE_UNKNOWN,
        KeyEvent.KEYCODE_VOLUME_DOWN,
        KeyEvent.KEYCODE_VOLUME_UP
    };
    private final static int EXTRA = 10; //space to create bookamarkNames/ids
    private final static int SHIFT = 2; //shift button names by url and file
    private SMain main;
    private StreamDB db;
    private AutoCompleteTextView uriEditText;
    private RadioButton uriRadioButton;
    private RadioButton fileRadioButton;
    private RadioGroup radioGroup;
    private MenuItem editMenu;
    private MenuItem deleteMenu;
    private int[] bookmarkId;
    private int bookmarkIdSize;
    private int selected;
    private int selectedIndex;
    private int fileId;
    private int uriId;
    private String[] bookmarkNames;
    private String name;
    private File pwd;
    private boolean staySelected;

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        db = new StreamDB(this);
        main = this;
        //remove any possible left over saved states
        db.deleteState();
        setupMainScreen();
    }

    public void onDestroy(){
        super.onDestroy();
        db.close();
    }

    public boolean onCreateOptionsMenu(Menu menu){
        editMenu=menu.add(0, EDIT_ID, 0, "Edit");
        deleteMenu=menu.add(0, DELETE_ID, 0, "Delete");
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item){
        int itemId = item.getItemId();
        switch (itemId){
            case EDIT_ID:
                showDialog(EDIT_ID);
                return true;
            case DELETE_ID:
                removeBookmark();
                return true;
        }
        return false;
    }

    public boolean onPrepareOptionsMenu(Menu menu){
        Log.v(TAG,"selected="+selected);
        if(selected == fileId || selected == uriId || selected == NONE){
            deleteMenu.setEnabled(false);
            editMenu.setEnabled(false);
        }else{
            deleteMenu.setEnabled(true);
            editMenu.setEnabled(true);
        }
        return true;
    }

    protected Dialog onCreateDialog(int id){
        Dialog dialog = null;
        switch(id){   
            case EDIT_ID:
            case CREATE_ID:
                dialog = new BookmarkDialog(this, id);
                break;
            default:
                dialog = null;
        }
        return dialog;
    }

    protected void onPrepareDialog(int id, Dialog d){
        BookmarkDialog dialog = (BookmarkDialog) d;
        dialog.setAction(id);
        switch(id){   
            case EDIT_ID:
                dialog.setName(name);
                dialog.setUri(getUri());
                break;
            case CREATE_ID:
                dialog.setName("");
                dialog.setUri(getUri());
                break;
            default:
                return;
        }
    }

    public String getUri(){
        return uriEditText.getText().toString();
    }
    
    protected String getSelectedName(){
        return name;
    }

    public void clearPwd(){
        pwd = null;
    }

    
    
    private void setupMainScreen(){
        setContentView(R.layout.main);
        uriEditText = (AutoCompleteTextView) findViewById(R.main.uriEditText);
        radioGroup = (RadioGroup) findViewById(R.main.radioGroup);
        uriRadioButton = (RadioButton) findViewById(R.main.uriRadioButton);
        fileRadioButton = (RadioButton) findViewById(R.main.fileRadioButton);
        final Button playButton = (Button) findViewById(R.main.playButton);
        final Button bookmarkButton = (Button) findViewById(R.main.bookmarkButton);
        //setupMainScreen: Set Listeners for Enter/Tab keys and clear 
        //selection when modified.
        uriEditText.setOnKeyListener(new OnKeyListener(){
            public boolean onKey(View v, int keyCode, KeyEvent event){
                final int ACTION_DOWN =  KeyEvent.ACTION_DOWN;
                final int KEYCODE_ENTER = KeyEvent.KEYCODE_ENTER;
                if(event.getAction()==KeyEvent.ACTION_DOWN && 
                    (keyCode==KeyEvent.KEYCODE_ENTER || keyCode==KeyEvent.KEYCODE_TAB)){
                    if(uriEditText.getListSelection()==NONE){
                        playButton.requestFocus();
                    }else{
                        uriEditText.performCompletion();
                    }
                    return true;
                }
                else if(event.getAction() == KeyEvent.ACTION_DOWN && 
                        (keyCode==KeyEvent.KEYCODE_DPAD_RIGHT)){
                        if(pwd!=null&&pwd.isDirectory()){
                            uriEditText.showDropDown();
                        }
                }
                return false;
            }
        });

        uriEditText.addTextChangedListener(new TextWatcher(){
            public void afterTextChanged(Editable s){
                if(getMatchingFiles(main, pwd, uriEditText)){
                    clearPwd();
                }
                if(selected!=NONE && !staySelected){
                    int cPos = uriEditText.getSelectionStart();
                    radioGroup.check(NONE);
                    if(cPos>uriEditText.length()){
                        cPos = uriEditText.length();
                    }
                    Selection.setSelection(uriEditText.getText(), cPos);
                }
            }
            public void onTextChanged(CharSequence s, int start, 
                        int before, int count){
            }
            public void beforeTextChanged(CharSequence s, int start, 
                        int count, int after){
            }
        });
        playButton.setOnClickListener(new OnClickListener(){
            public void onClick(View v){
                setupVideo();
            }
        });
        bookmarkButton.setOnClickListener(new OnClickListener(){
            public void onClick(View v){
                showDialog(CREATE_ID);
            }
        });
        uriId = uriRadioButton.getId();
        fileId = fileRadioButton.getId();
        registerForContextMenu(radioGroup);
        radioGroup.setOnCheckedChangeListener( 
                    new RadioGroup.OnCheckedChangeListener(){
            public void onCheckedChanged(RadioGroup rg, int checkedID){
                if(selected!=checkedID){
                    staySelected = true;
                    selected = checkedID;
                    setBookmark(checkedID);
                    staySelected = false;
                }
            }
        });
        String[] names = db.viewBookmarks();
        int len = names.length;
        bookmarkIdSize = len;
        bookmarkId = new int[len+EXTRA];
        bookmarkNames = new String[len+EXTRA];
        int pos = radioGroup.getChildCount();
        for(int i=0; i<len; ++i){
            RadioButton btn = new RadioButton(this);
            RadioGroup.LayoutParams params = 
                new RadioGroup.LayoutParams(
                                ViewGroup.LayoutParams.WRAP_CONTENT,
                                ViewGroup.LayoutParams.WRAP_CONTENT);
            btn.setText(names[i]);
            radioGroup.addView(btn, pos+i, params);
            bookmarkId[i] = btn.getId();
            bookmarkNames[i] = names[i];
        }
        radioGroup.check(NONE);
    }

    private void setBookmark(int checkedID){
        String uri = "";
        selectedIndex = NONE;
        name = null;
        if(checkedID==NONE){
            return;
        }else if(checkedID==fileId){
            uri=FILE_URL;
        }else if(checkedID==uriId){
            uri=NO_URL;
        }else{
            for(int i=0; i<bookmarkIdSize; ++i){
                if(bookmarkId[i] == checkedID){
                    name = bookmarkNames[i];
                    uri = db.getBookmarkUri(name);
                    selectedIndex = i;
                    break;
                }
            }
        }
        uriEditText.setText(uri);
    }

    protected void saveBookmark(String name, String uri){
        boolean success = db.saveBookmark(name, uri, 0);
        if(!success){
           Toast.makeText(this, "Error: \nFailed to save bookmark. Is the name taken?", Toast.LENGTH_SHORT).show(); 
            return;
        }
        if(!uri.equals(uriEditText.getText().toString())){
            uriEditText.setText(uri);
        }
        dismissDialog(CREATE_ID);
        RadioButton btn = new RadioButton(this);
        final int w = ViewGroup.LayoutParams.WRAP_CONTENT;
        RadioGroup.LayoutParams params = new RadioGroup.LayoutParams(w, w);
        btn.setText(name);
        int pos = radioGroup.getChildCount();
        radioGroup.addView(btn, pos, params);
        bookmarkId[bookmarkIdSize] = btn.getId();
        bookmarkNames[bookmarkIdSize] = name;
        bookmarkIdSize += 1;
        if(bookmarkIdSize == bookmarkId.length-1){
            resizeBookmarks(EXTRA);
        }
        radioGroup.check(btn.getId());
    }

    protected void editBookmark(String oldName, String name, String uri){
        db.editBookmark(oldName, name, uri, 0);
        if(!uri.equals(uriEditText.getText().toString())){
            uriEditText.setText(uri);
        }
        for(int i = 0; i<bookmarkIdSize; ++i){
            if(bookmarkNames[i].equals(oldName)){
                ((RadioButton)radioGroup.getChildAt(i+SHIFT)).setText(name);
                bookmarkNames[i]=name;
            }
        }
        dismissDialog(EDIT_ID);

    }

    private void removeBookmark(){
        db.removeBookmark(name);
        radioGroup.removeViewAt(selectedIndex+SHIFT);
        int edge = bookmarkIdSize-1;
        for(int i = selectedIndex; i<edge; ++i){
            bookmarkNames[i] = bookmarkNames[i+1];
            bookmarkId[i] = bookmarkId[i+1];
        }
        bookmarkNames[bookmarkIdSize] = "";
        bookmarkId[bookmarkIdSize] = NONE;
        selectedIndex = NONE;
        bookmarkIdSize -= 1;
        selected = NONE;
        name = "";
    }

    private void resizeBookmarks(int amount){
        int[] tmpI = new int[bookmarkId.length+amount];
        String[] tmpS = new String[bookmarkNames.length+amount];
        for(int i=0; i<bookmarkIdSize; ++i){
            tmpI[i] = bookmarkId[i];
            tmpS[i] = bookmarkNames[i];
        }
        bookmarkId = tmpI;
        bookmarkNames = tmpS;
    }

    protected void setupVideo(){
        Uri uri = null;
        uri = Uri.parse(uriEditText.getText().toString());
        Intent intent = new Intent(Intent.ACTION_VIEW, uri, getApplication(), SPlayer.class);
        if(name != null && !name.equals("")){
            intent.putExtra("name", name);
        }
        startActivity(intent);
    }

    public static boolean isModifierKey(int key){
        int len = NON_MODIFIER_KEYS.length;
        for(int i=0; i<len; ++i){
            if(key==NON_MODIFIER_KEYS[i]){
                return false;
            }
        }
        return true;
    }

    public static boolean getMatchingFiles(SMain sm, File pwd, AutoCompleteTextView editText){
        String text = editText.getText().toString();
        Log.v(TAG,"@@getMatchingFiles");
        if(text==null || text.length()==0){
            return false;
        }
        int sLen = text.length();
        boolean isSchema = (sLen>5 && 
            text.substring(0,FILE_SCHEMA.length()).equals(FILE_SCHEMA));
        boolean isPath = (sLen>0 && text.charAt(0)==File.separatorChar) || 
            isSchema;
        if(isPath){
            int pathEnd = text.lastIndexOf((int)File.separatorChar);
            int pathStart = 0;
            if(isSchema){
                pathStart = FILE_SCHEMA.length();
            }
            Log.v(TAG,"@@$"+(text.charAt(0))+"$$"+text.substring(pathStart,pathEnd)+"$");
            String path = text.substring(pathStart, pathEnd); 
            if(pwd==null || !pwd.getPath().equals(path)){
                pwd = new File(path);
                if(pwd.isDirectory()){
                    File[] files = pwd.listFiles();
                    int len = files.length;
                    String[] list = new String[len];
                    for(int i=0; i<len; ++i){
                        Log.v(TAG,"@@ "+files[i]);
                        list[i] = files[i].getPath();
                        if(files[i].isDirectory()){
                            list[i] += "/";
                        }
                        if(isSchema){
                            list[i] = FILE_SCHEMA+list[i];
                        }
                    }
                    editText.setAdapter(new ArrayAdapter<String>(sm,
                        android.R.layout.simple_dropdown_item_1line, list));
                }
            }
        }else{
            return false;
        }
        return pwd != null;
    }
}

class BookmarkDialog extends Dialog{
    private final static String EDIT_TITLE = "Edit Bookmark";
    private final static String CREATE_TITLE = "Create Bookmark";
    private final SMain main;
    private File pwd;
    private AutoCompleteTextView uriViewBookmark;
    private EditText nameViewBookmark;
    private int actionId;

    public BookmarkDialog(SMain m, int action){
        super(m);
        this.main = m;
        setTitle(action);
        setContentView(R.layout.bookmark_dialog);
        uriViewBookmark = (AutoCompleteTextView) findViewById(R.bookmark_dialog.url);
        nameViewBookmark = (EditText) findViewById(R.bookmark_dialog.name);
        final Button ok = (Button) findViewById(R.bookmark_dialog.ok);
        final Button cancel = (Button) findViewById(R.bookmark_dialog.cancel);
        uriViewBookmark.setOnKeyListener(new View.OnKeyListener(){
            public boolean onKey(View v, int keyCode, KeyEvent event){
                final int ACTION_DOWN =  KeyEvent.ACTION_DOWN;
                final int KEYCODE_ENTER = KeyEvent.KEYCODE_ENTER;
                if(event.getAction()==KeyEvent.ACTION_DOWN && 
                    (keyCode==KeyEvent.KEYCODE_ENTER || keyCode==KeyEvent.KEYCODE_TAB)){
                    if(uriViewBookmark.getListSelection()==SMain.NONE){
                        nameViewBookmark.requestFocus();
                    }else{
                        uriViewBookmark.performCompletion();
                    }
                    return true;
                }
                else if(event.getAction() == KeyEvent.ACTION_DOWN && 
                        (keyCode==KeyEvent.KEYCODE_DPAD_RIGHT)){
                        if(pwd!=null&&pwd.isDirectory()){
                            uriViewBookmark.showDropDown();
                        }
                }
                return false;
            }
        });
        uriViewBookmark.addTextChangedListener(new TextWatcher(){
            public void afterTextChanged(Editable s){
                if(SMain.getMatchingFiles(main, pwd, uriViewBookmark)){
                    clearPwd();
                }
            }
            public void onTextChanged(CharSequence s, int start, 
                        int before, int count){
            }
            public void beforeTextChanged(CharSequence s, int start, 
                        int count, int after){
            }
        });

        /*.setOnKeyListener(new View.OnKeyListener(){
            public boolean onKey(View v, int keyCode, KeyEvent event){
                final int ACTION_DOWN =  KeyEvent.ACTION_DOWN;
                final int KEYCODE_ENTER = KeyEvent.KEYCODE_ENTER;
                if((event.getAction() == ACTION_DOWN) && (keyCode == KEYCODE_ENTER)){
                    nameViewBookmark.requestFocus();
                    return true;
                }
                return false;
            }
        });*/
        nameViewBookmark.setOnKeyListener(new View.OnKeyListener(){
            public boolean onKey(View v, int keyCode, KeyEvent event){
                final int ACTION_DOWN =  KeyEvent.ACTION_DOWN;
                final int KEYCODE_ENTER = KeyEvent.KEYCODE_ENTER;
                if((event.getAction() == ACTION_DOWN) && (keyCode == KEYCODE_ENTER)){
                    ok.requestFocus();
                    return true;
                }
                return false;
            }
        });
        ok.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                doAction(actionId);
            }
        });
        cancel.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                main.dismissDialog(actionId);
            }
        });
    }

    private void doAction(int action){
        if(action == SMain.CREATE_ID){
            main.saveBookmark(getName(), getUri());
        }else if(action == SMain.EDIT_ID){
            String oldName = main.getSelectedName();
            main.editBookmark(oldName, getName(), getUri());
        }
    }

    public void setAction(int action){
        actionId = action;
        setTitle(action);
    }

    public void setTitle(int action){
        if(action == SMain.EDIT_ID){
            setTitle(EDIT_TITLE);
        }else if(action == SMain.CREATE_ID){
            setTitle(CREATE_TITLE);
        }
    }

    public void clearPwd(){
        pwd = null;
    }

    public void setUri(String uri){
        uriViewBookmark.setText(uri);
    }

    public void setName(String name){
        nameViewBookmark.setText(name);
    }

    public String getUri(){
        return uriViewBookmark.getText().toString();
    }

    public String getName(){
        return nameViewBookmark.getText().toString();
    }

}

